//
// GPSMapEdit
// (c) Konstantin Galichsky (kg@geopainting.com), 2006
//
// Set routing graph turn restrictions.
//

# include "StdAfx.h"
# include "SetRGNodeRestriction.h"
# include "UndoRedo.h"
# include "RGNodes.h"

class CAddRGNodeRestrictionAction : public CEditAction {
  public:
	CAddRGNodeRestrictionAction (const rgrestriction_t & _restriction) :
		m_pRestriction (NULL),
		m_restriction (_restriction)
	{}

	virtual void GetName (string_t & _str) const;
	virtual cu_t CanUndo () const {return cuYes;}
	virtual bool Do ();
	virtual void Undo ();
	virtual void Redo ();

  private:
	rgrestriction_t * m_pRestriction;
	rgrestriction_t   m_restriction;
};

void CAddRGNodeRestrictionAction::GetName (string_t & _str) const {
	_str.append ("add turn restriction");
}

bool CAddRGNodeRestrictionAction::Do () {
	CCritSec::CLock lock (g_cs);

	rgrestriction_t & restriction = AddRGNodeRestriction (g_map, m_restriction.pNode);
	restriction = m_restriction;
	restriction.pNode->bHasRestrictions = true;

	assert (m_pRestriction == NULL);
	m_pRestriction = & restriction;

	return true;
}

void CAddRGNodeRestrictionAction::Undo () {
	CCritSec::CLock lock (g_cs);

	const rgrestrictions_t::iterator ir = FindRGNodeRestriction (g_map.rgrestrictions, * m_pRestriction);
	if (ir == g_map.rgrestrictions.end ())
		return;

	m_restriction.pNode->bHasRestrictions = g_map.rgrestrictions.find (m_restriction.pNode) != g_map.rgrestrictions.end ();

	g_map.rgrestrictions.erase (ir);
	m_pRestriction = NULL;
}

void CAddRGNodeRestrictionAction::Redo () {
	CAddRGNodeRestrictionAction::Do ();
}

void AddRGNodeRestriction (const rgrestriction_t & _restriction) {
	PerformEditAction (new CAddRGNodeRestrictionAction (_restriction));
}

////////////////////////////////////////////////

class CRemoveRGNodeRestrictionAction : public CEditAction {
  public:
	CRemoveRGNodeRestrictionAction (rgrestriction_t & _restriction) :
		m_pRestriction (& _restriction),
		m_restriction_saved (_restriction)
	{}

	virtual void GetName (string_t & _str) const;
	virtual cu_t CanUndo () const {return cuYes;}
	virtual bool Do ();
	virtual void Undo ();
	virtual void Redo ();

  private:
	rgrestriction_t * m_pRestriction;
	rgrestriction_t   m_restriction_saved;
};

void CRemoveRGNodeRestrictionAction::GetName (string_t & _str) const {
	_str.append ("remove turn restriction");
}

bool CRemoveRGNodeRestrictionAction::Do () {
	CCritSec::CLock lock (g_cs);

	const rgrestrictions_t::iterator ir = FindRGNodeRestriction (g_map.rgrestrictions, * m_pRestriction);
	if (ir == g_map.rgrestrictions.end ())
		return false;

	g_map.rgrestrictions.erase (ir);
	m_pRestriction = NULL;

	m_restriction_saved.pNode->bHasRestrictions = g_map.rgrestrictions.find (m_restriction_saved.pNode) != g_map.rgrestrictions.end ();

	return true;
}

void CRemoveRGNodeRestrictionAction::Undo () {
	CCritSec::CLock lock (g_cs);

	rgrestriction_t & restriction = AddRGNodeRestriction (g_map, m_restriction_saved.pNode);
	restriction = m_restriction_saved;
	restriction.pNode->bHasRestrictions = true;

	assert (m_pRestriction == NULL);
	m_pRestriction = & restriction;
}

void CRemoveRGNodeRestrictionAction::Redo () {
	CRemoveRGNodeRestrictionAction::Do ();
}

void RemoveRGNodeRestriction (rgrestriction_t & _restriction) {
	PerformEditAction (new CRemoveRGNodeRestrictionAction (_restriction));
}
